#pragma once
#include <iostream>
#include <queue>
#include <pthread.h>
#include "Log.hpp"
#include "Task.hpp"


#define NUM 6

class ThreadPool
{
    private:
        int num; //线程池的线程数量
        bool stop;
        std::queue<Task> task_queue; //任务队列
        pthread_mutex_t lock; //互斥锁
        pthread_cond_t cond; //条件变量

        //线程池初始化
        ThreadPool(int _num = NUM)
            :num(_num)
            ,stop(false)
        {
            //初始化互斥锁
            pthread_mutex_init(&lock,nullptr);
            //初始化条件变量
            pthread_cond_init(&cond,nullptr);
        }
        //线程池设计成单例模式: 拷贝构造和赋值运算符重载函数私有化
        ThreadPool(const ThreadPool&) = delete;
        ThreadPool& operator=(const ThreadPool&) = delete;
        static ThreadPool* single_instance;
    public:

        static ThreadPool* GetInstance()
        {
            //互斥锁静态初始化
            static pthread_mutex_t _mutex = PTHREAD_MUTEX_INITIALIZER;
            if(single_instance == nullptr)
            {
                pthread_mutex_lock(&_mutex);
                if(single_instance == nullptr)
                {
                    //创建线程池对象，并且对线程池进行初始化
                    single_instance = new ThreadPool();
                    single_instance->InitThreadPool();
                }
                pthread_mutex_unlock(&_mutex);
            }
            return single_instance;
        }

        //线程池当前是否在运行
        bool IsStop()
        {
            return stop;
        }

        //判断线程池任务队列是否为空
        bool TaskQueueEmpty()
        {
            return task_queue.size() == 0 ? true : false;
        }

        //加锁
        bool Lock()
        {
            pthread_mutex_lock(&lock);
        }
        //解锁
        bool UnLock()
        {
            pthread_mutex_unlock(&lock);
        }

        //线程等待
        void ThreadWait()
        {
            pthread_cond_wait(&cond,&lock);
        }
        //唤醒线程
        void ThreadWakeup()
        {
            pthread_cond_signal(&cond);
        }

        //线程执行函数: 参数是this指针
        static void* ThreadRoutine(void* args)
        {
            ThreadPool* tp = (ThreadPool*)args;

            while(true)
            {
                Task t;
                tp->Lock();
                //当任务队列为空时,则进行等待
                while(tp->TaskQueueEmpty()){
                    tp->ThreadWait();
                }
                //任务队列有任务时,则取出任务
                tp->PopTask(t);
                tp->UnLock();
                //执行任务
                t.ProcessOn();
            }
        }
        //初始化线程池中的线程
        bool InitThreadPool()
        {
            for(int i = 0;i < num;i++)
            {
                pthread_t tid;
                if(pthread_create(&tid,nullptr,ThreadRoutine,this) != 0)
                {
                    LOG(FATAL,"create thread pool error!");
                    return false;
                }
            }
            LOG(INFO,"create thread pool success!");
            return true;
        }
        //添加任务
        void PushTask(const Task& task)
        {
            Lock();
            task_queue.push(task);
            UnLock();
            //唤醒线程,执行任务
            ThreadWakeup();
        }
        //取走任务
        void PopTask(Task& task)
        {
            task = task_queue.front();
            task_queue.pop();
        }
        //线程池析构
        ~ThreadPool()
        {
            pthread_mutex_destroy(&lock);
            pthread_cond_destroy(&cond);
        }
};

ThreadPool* ThreadPool::single_instance = nullptr;
